#pragma once

#include "vector3.h"
#include <list>
#include <string>

namespace krryn{
namespace view{
	typedef unsigned int pixel_t;
    typedef char color_t;

	class canvas{
	public:
		enum scale_quality{
			scale_linear,
			scale_bilinear,
			scale_bicubic
		};

		canvas();
		canvas(const std::string &a_Filename);
		canvas(int a_Width, int a_Height);
		~canvas();

		void set_buffer(pixel_t *a_Pixel);
		void set_width(int a_Width);
		void set_height(int a_Height);
		void set_pitch(int a_Pitch);

		pixel_t *get_buffer() const { return m_Pixels; }
		int get_width() const { return m_Width; }
		int get_height() const { return m_Height; }
		int get_pitch() const { return m_Pitch; }

		void clear(pixel_t a_Pixel);

        void circle(int a_X, int a_Y, int a_Radius, pixel_t a_Color);
		void paint(int x, int y, pixel_t a_Color);
		math::color3 color_at(int x, int y);

		pixel_t mix_color(color_t r, color_t g, color_t b) const;
		pixel_t mix_color(const math::color3 &a_Color) const;

		void lock();
		void unlock();

        void copy_to(canvas *a_Other);
		canvas *resize(int a_With, int a_Height, scale_quality a_Quality);
		std::list<canvas*> generate_mip_maps(scale_quality a_Quality = scale_bicubic);

		void store(const std::string &a_Filename);
        
    private:
        pixel_t get_pixel(int x, int y);
        color_t clamp(const float a_Value) const;

		void resize_to_linear(canvas *a_Target);
		void resize_to_bilinear(canvas *a_Target);
		void resize_to_bicubic(canvas *a_Target);
        
   		pixel_t *m_Pixels;
		int m_Width;
		int m_Height;
		int m_Pitch;
		bool m_Locked;
	};
}
}
